#include <cstdio>
#include <iostream>
#include <string>

#if defined(_WIN32) || defined(__WIN32__)
#include <direct.h>
#include <io.h>
// create directory
#define mkdir _mkdir
// file for directory is exist?
#define access _access
// remove directory
#define rmdir _rmdir
// change file or directory access
#define chmod _chmod
// duplicates strings
#define strdup _strdup
// is file or directory?
#define stat _stat
// remove file or directory
#define unlink _unlink
// change current directory
#define chdir _chdir
// get current directory
#define getcwd _getcwd
// windows is not exist!!!
#define readdir
#else
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
#include <errno.h>

/// 递归构造目录
/// [newdir] 指定构建目录路径
/// 成功返回1，否则返回0
int makedir(const char *newdir) {
  char *buffer = strdup(newdir);
  char *p;
  int len = strlen(buffer);

  if (len <= 0) {
    free(buffer);
    return 0;
  }
  if (buffer[len - 1] == '/') {
    buffer[len - 1] = '\0';
  }
  if (mkdir(buffer, 0755) == 0) {
    free(buffer);
    return 1;
  }

  p = buffer + 1;
  while (1) {
    char hold;

    while (*p && *p != '\\' && *p != '/')
      p++;
    hold = *p;
    *p = 0;
    if ((mkdir(buffer, 0755) == -1) && (errno == ENOENT)) {
      fprintf(stderr, "Couldn't create directory %s\n", buffer);
      free(buffer);
      return 0;
    }
    if (hold == 0)
      break;
    *p++ = hold;
  }
  free(buffer);
  return 1;
}

/// 递归删除目录以及包含的文件
/// [path] 指定将要删除的目录路径
/// 成功返回1，否则返回0
int removedir(const char *path) {
#if defined(_WIN32) || defined(__WIN32__)
  fprintf(stderr, "%s: %s\n", "Windows not support remove dir.", path);
#else
  size_t path_len;
  char *full_path;
  DIR *dir;
  struct stat stat_path, stat_entry;
  struct dirent *entry;

  // stat for the path
  stat(path, &stat_path);

  // if path does not exists or is not dir - exit with status -1
  if (S_ISDIR(stat_path.st_mode) == 0) {
    fprintf(stderr, "%s: %s\n", "Is not directory", path);
    return 0;
  }

  // if not possible to read the directory for this user
  if ((dir = opendir(path)) == NULL) {
    fprintf(stderr, "%s: %s\n", "Can`t open directory", path);
    return 0;
  }

  // the length of the path
  path_len = strlen(path);

  // iteration through entries in the directory
  while ((entry = readdir(dir)) != NULL) {

    // skip entries "." and ".."
    if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
      continue;

    // determinate a full path of an entry
    full_path =
        (char *)calloc(path_len + strlen(entry->d_name) + 1, sizeof(char));
    strcpy(full_path, path);
    strcat(full_path, "/");
    strcat(full_path, entry->d_name);

    // stat for the entry
    stat(full_path, &stat_entry);

    // recursively remove a nested directory
    if (S_ISDIR(stat_entry.st_mode) != 0) {
      removedir(full_path);
      continue;
    }

    // remove a file object
    if (unlink(full_path) == 0)
      printf("Removed a file: %s\n", full_path);
    else
      printf("Can`t remove a file: %s\n", full_path);
    free(full_path);
  }

  // remove the devastated directory and close the object of it
  if (rmdir(path) == 0)
    printf("Removed a directory: %s\n", path);
  else
    printf("Can`t remove a directory: %s\n", path);

  closedir(dir);
#endif
  return 1;
}

/// 目录是否存在
/// [path] 指定目录路径
/// 存在返回1，否则返回0
int dirisexist(const char *path) {
  struct stat stat_entry;
  stat(path, &stat_entry);
  if (S_ISDIR(stat_entry.st_mode) != 0) {
    return 1;
  }
  return 0;
}

/// 文件是否存在
/// [path] 指定目录路径
/// 存在返回1，否则返回0
int fileisexist(const char *path) {
  struct stat stat_entry;
  stat(path, &stat_entry);
  if (S_ISREG(stat_entry.st_mode) != 0) {
    return 1;
  }
  return 0;
}

/// 删除文件
/// [path] 指定文件路径
/// 成功返回1，否则返回0
int removefile(const char *path) {
  if (unlink(path) == 0) {
    return 1;
  }
  return 0;
}

/// 改变当前目录
/// [path] 指定文件路径
/// 成功返回1，否则返回0
int changecurdir(const char *path) {
  if (chdir(path) == 0) {
    return 1;
  }
  return 0;
}

/// 获取当前目录
/// [path] 获取当前文件路径，成功后需要释放内存
/// 成功返回1，否则返回0
int getcurdir(char *path, int path_max_size) {
  char *buffer = getcwd(NULL, path_max_size);
  if (buffer != NULL) {
    memcpy(path, buffer, strlen(buffer));
    free(buffer);
    return 1;
  }
  return 0;
}

int main(int argc, char const *argv[]) {
  //  int ret = mkdir("/Volumes/data/tmp/test/test2/test3", 0755);
  //  int ret = rmdir("/Volumes/data/tmp/test/test2");
  //  int ret = access("/Volumes/data/tmp/test/test2", 755);
  //  int ret = makedir("/Volumes/data/tmp/test/test2/test4/test5/test6/");
  //  int ret = makedir("/Volumes/data/tmp/test/test2/test4/test5/test6");
  //  int ret = removedir("/Volumes/data/tmp/test/test2/");
  //    int ret = removedir("/Volumes/data/tmp/test/test2");
  //  int ret = dirisexist("/Volumes/data/tmp/test/test5");
  // int ret = dirisexist("/Volumes/data/tmp/test/test5/");
  //  int ret = fileisexist("/Volumes/data/tmp/test/testfile.text");
  //  int ret = fileisexist("/Volumes/data/tmp/test/testfile");
  //  int ret = removefile("/Volumes/data/tmp/test/testfile.text");
  int ret = changecurdir("/Volumes/data/tmp/test/test2");
  char path[1024] = {0};
  int ret2 = getcurdir(&path[0], 1024);
  std::string output;
  output = std::string(path);
  printf("ret=%d\n", ret);
  return 0;
}
